package com.xt.tea.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.xt.tea.entity.domain.AbstractDomain;
import com.xt.tea.entity.enums.RequestResultEnum;
import com.xt.tea.entity.exception.GlobalException;
import com.xt.tea.mapper.AbstractDomainMapper;
import lombok.extern.slf4j.Slf4j;

import java.lang.reflect.Field;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;

@Slf4j
public class BaseService {

    /**
     * 统一新增操作
     * @param mapper mapper
     * @param obj 新增对象
     * @return 新增结果
     * @param <T> 新增对象类型
     */
    public <T extends AbstractDomain> int  insert(AbstractDomainMapper<T> mapper,T obj){
        obj.setCreateTime(new Date());
        obj.setUpdateTime(new Date());
        obj.setDeleteFlag(false);
        obj.setDataStatus(true);
        return mapper.insert(obj);
    }

    /**
     * 统一更新操作
     * @param mapper mapper
     * @param obj 更新的对象
     * @return 更新后的对象
     * @param <T> 更新对象类型
     */
    public <T extends AbstractDomain> T update(AbstractDomainMapper<T> mapper,T obj,T oldObj){
        if (oldObj==null){
            throw new GlobalException(RequestResultEnum.UPDATE_ERROR_NO_RECORDS);
        }
        int diffFieldCount = copyProperties(obj, oldObj);
        if (diffFieldCount==0){
            log.info("新旧记录对比,属性没有发生变化,不需要更新");
            return obj;
        }
        oldObj.setUpdateTime(new Date());
        mapper.updateById(oldObj);
        return oldObj;
    }

    /**
     * 启停用记录
     * @param mapper mapper
     * @param obj 需要启停的记录
     * @return 结果
     * @param <T> 启停记录类型
     */
    public <T extends AbstractDomain> T updateDataStatusById(AbstractDomainMapper<T> mapper,T obj){
        obj.setDataStatus(!obj.getDataStatus());
        obj.setUpdateTime(new Date());
        mapper.updateById(obj);
        return obj;
    }

    /**
     * 删除记录
     * @param mapper mapper
     * @param obj 需要启停的记录
     * @return 结果
     * @param <T> 启停记录类型
     */
    public <T extends AbstractDomain> int deleteById(AbstractDomainMapper<T> mapper,T obj){
        Integer id = obj.getId();
        T t = this.selectById(mapper,id);
        t.setDeleteFlag(true);
        t.setUpdateTime(new Date());
        return mapper.updateById(t);
    }

    private <T extends AbstractDomain> int copyProperties(T sourceObj, T targetObj){
        int result = 0;
        try{
            Class<? extends AbstractDomain> clazz = sourceObj.getClass();
            Field[] fields = clazz.getDeclaredFields();
            for (Field field : fields) {
                field.setAccessible(true);
                Object newObj = field.get(sourceObj);
                Object oldObj = field.get(targetObj);
                if (!Objects.equals(newObj,oldObj)){
                    result++;
                    field.set(targetObj,newObj);
                }
            }
        }catch (IllegalAccessException e){
            log.error("新旧记录拷贝出错,请联系管理员处理");
            throw new GlobalException(RequestResultEnum.UPDATE_COPY_ERROR);
        }
        return result;
    }

    public  <T extends AbstractDomain> T selectById(AbstractDomainMapper<T> mapper,Integer id){
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("id",id)
                .eq("delete_flag",false);
        return mapper.selectOne(queryWrapper);
    }

    public  <T extends AbstractDomain> List<T> selectByIdList(AbstractDomainMapper<T> mapper, Set<Integer> idList){
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("id",idList)
                .eq("delete_flag",false);
        return mapper.selectList(queryWrapper);
    }
}
